package top.littlejiang.onlinexam.common.utils;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.interfaces.DecodedJWT;
import top.littlejiang.onlinexam.entity.OlexamUser;

import javax.servlet.ServletRequest;
import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * Token 相关
 * @author chen
 * @Description
 * @since 2021/1/2 16:17
 */
public class JWTUtils {
    /**
     * token有效时长
     */
    private static final long EXPIRE=24 * 60 * 60 * 1000L;
    /**
     * token的密钥
     */
    private static final String SECRET="ddf3681b6ecb76e9ab2f285cec78c2e0";
    /**
     * 与前端统一的位于请求头的token参数名
     */
    public static final String TOKEN_NAME = "ClientToken";
    /**
     * 在token中UserId的参数名，可用于向Controller中传入用户Id
     */
    public static final String USER_ID_IN_TOKEN = "userId";
    /**
     * 在token中UserName的参数名，可用于向Controller中传入用户名
     */
    public static final String USER_NAME_IN_TOKEN = "userName";
    /**
     * 在token中UserRoleSign的参数名，可用于向Controller中传入用户角色
     */
    public static final String USER_ROLE_IN_TOKEN = "userRoleSign";


    public static String createToken(OlexamUser user) throws UnsupportedEncodingException {
        //token过期时间
        Date date=new Date(System.currentTimeMillis()+EXPIRE);

        //jwt的header部分
        Map<String ,Object> map=new HashMap<>(5);
        map.put("alg","HS256");
        map.put("typ","JWT");

        //使用jwt的api生成token
        String token= JWT.create()
                .withHeader(map)
                //私有声明
                .withClaim(USER_NAME_IN_TOKEN, user.getUserName())
                .withClaim(USER_ID_IN_TOKEN,user.getId())
                .withClaim(USER_ROLE_IN_TOKEN,user.getRoleSign())
                //过期时间
                .withExpiresAt(date)
                //签发时间
                .withIssuedAt(new Date())
                //签名
                .sign(Algorithm.HMAC256(SECRET));
        return token;
    }

    /**
     * 校验token的有效性，
     * 1、token的header和payload是否没改过；2、没有过期
     * @param token
     * @return
     */
    public static boolean verify(String token){
        try {
            //解密
            JWTVerifier verifier=JWT.require(Algorithm.HMAC256(SECRET)).build();
            verifier.verify(token);
            return true;
        }catch (Exception e){
            return false;
        }
    }

    /**
     * 无需解密也可以获取token的信息
     * @param token
     * @return
     */
    public static int getUserId(String token){
        try {
            DecodedJWT jwt = JWT.decode(token);
            return jwt.getClaim(USER_ID_IN_TOKEN).asInt();
        } catch (JWTDecodeException e) {
            return 0;
        }
    }

    public static int getUserId(){
        return (int)HttpContextUtils.getHttpServletRequest().getAttribute(JWTUtils.USER_ID_IN_TOKEN);
    }

    public static String getUserName(){
        return (String)HttpContextUtils.getHttpServletRequest().getAttribute(JWTUtils.USER_NAME_IN_TOKEN);
    }

    public static String getUserName(String token){
        try {
            DecodedJWT jwt = JWT.decode(token);
            return jwt.getClaim(USER_NAME_IN_TOKEN).asString();
        } catch (JWTDecodeException e) {
            return null;
        }
    }

    public static String getUserRole(String token){
        try {
            DecodedJWT jwt = JWT.decode(token);
            return jwt.getClaim(USER_ROLE_IN_TOKEN).asString();
        } catch (JWTDecodeException e) {
            return null;
        }
    }

}
